package com.koron.ticket.operation.controller;


import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageInfo;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.annocation.CasUser;
import com.koron.common.core.business.print.ReportTask;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.StringUtils;
import com.koron.ticket.enums.ApprovEnum;
import com.koron.ticket.enums.OperationGroupEnum;
import com.koron.ticket.enums.OperationTypeEnum;
import com.koron.ticket.enums.SubmitEnum;
import com.koron.ticket.operation.bean.OperationDescBean;
import com.koron.ticket.operation.bean.OperationExecuteBean;
import com.koron.ticket.operation.bean.OperationStepBean;
import com.koron.ticket.operation.bean.OperationTicketBean;
import com.koron.ticket.operation.bean.dto.*;
import com.koron.ticket.operation.bean.excelbean.OperationFactoryTemplate;
import com.koron.ticket.operation.bean.excelbean.OperationStepBaseTemplate;
import com.koron.ticket.operation.bean.excelbean.OperationStepTemplate;
import com.koron.ticket.operation.bean.print.OperationFactoryBean;
import com.koron.ticket.operation.mapper.OperationExecuteMapper;
import com.koron.ticket.operation.mapper.OperationStepMapper;
import com.koron.ticket.operation.mapper.OperationTicketMapper;
import com.koron.ticket.operation.mapper.OperationWorkMapper;
import com.koron.ticket.operation.service.OperationService;
import com.koron.ticket.utils.ExportExcelUtil;
import com.koron.ticket.utils.InitData;
import com.koron.ticket.utils.PrintUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.koron.ebs.mybatis.ADOConnection;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


@Slf4j
@RequestMapping("/operation")
@RestController
@Api(tags = "操作票")
public class OperationController {

    @Autowired
    private OperationService operationservice;

//    @Resource
//    private TalentImportVerifyHandler talentImportVerifyHandler;
//
//    @Resource
//    private FactoryTalentImportVerifyHandler factorytalentimportverifyhandler;

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    @PostMapping("/saveOrUpdate")
    @ApiOperation(value = "新增或保存操作票")
    public Response saveOrUpdate(@RequestBody OperationTicketDetailsDto dto) {
        Assert.isFalse(ObjectUtil.isEmpty(dto.getType()), "请补充操作票子类");
        if (dto.getType().equals(OperationTypeEnum.TYPE_A.getValue()) || dto.getType().equals(OperationTypeEnum.TYPE_B.getValue())) {
            Assert.isFalse(CollUtil.isEmpty(dto.getWorkIds()), "请补充工作票");
        }
        OperationTicketBean bean = new OperationTicketBean();
        BeanUtils.copyProperties(dto, bean);
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "saveOrUpdate", String.class, bean));
    }

    @PostMapping("/recordContext")
    @ApiOperation(value = "保存批注")
    public Response recordContext(@RequestBody OperationDescBean bean) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "recordContext", Integer.class, bean));
    }

    @ApiOperation(value = "根据操作票id删除 ")
    @DeleteMapping("/deleteById")
    public Response deleteById(@RequestParam("id") String id) {
        OperationTicketBean operationTicketBean = ADOConnection.runTask(getCurrDs(), factory -> {
            return factory.getMapper(OperationTicketMapper.class).selectByPrimaryKey(id);
        }, OperationTicketBean.class);
        Assert.isFalse(operationTicketBean.getStatus() == ApprovEnum.REVIEWED.getIntValue(), "票据已生成不允许删除");
        Assert.isFalse(operationTicketBean.getStatus() == ApprovEnum.ARCHIVED.getIntValue(), "票据已归档不允许删除");
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "deleteById", Integer.class, id));
    }

    @ApiOperation(value = "根据操作票id查询 ")
    @GetMapping("/queryByOrderId")
    public Response queryById(@RequestParam("id") String id) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "queryById", OperationTicketDetailsDto.class, id));
    }

    @ApiOperation(value = "查询 列表")
    @GetMapping("/queryList")
    public Response queryList(OperationTicketQueryDto queryBean) {
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "queryList", PageInfo.class, queryBean));
    }

    @ApiOperation(value = "交接班 远程调用 接口列表 无分页")
    @GetMapping("/queryListNoPage")
    public Response queryListNoPage(OperationTicknNewsDto dto) {
        if (StrUtil.equalsAny(getCurrDs(), "_default", "eam_system")){
            return Response.ok(new ArrayList());
        }
        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "queryListNoPage", List.class, dto));
    }

    @ApiOperation(value = "审核 含作废操作 ")
    @GetMapping("/submit")
    public Response submit(OperationSubmitDto dto) {

        //操作票信息
        OperationTicketBean bean = ADOConnection.runTask(getCurrDs(), factory -> {
            return factory.getMapper(OperationTicketMapper.class).selectByPrimaryKey(dto.getId());
        }, OperationTicketBean.class);

        Assert.isFalse(bean.getStatus().compareTo(dto.getNowStatus()) != 0, "当前加节点已过期");

        if (dto.getIsDuty() != null && dto.getIsDuty() == BigDecimal.ZERO.intValue()) {
            Assert.isFalse(dto.getGuardian() == dto.getDutyMan(), "监护人帐号与值班负责人帐号相同");
        } else {
            dto.setDutyMan(dto.getGuardian());
            dto.setDutyManName(dto.getGuardianName());
        }

        Assert.isFalse(bean.getStatus() == ApprovEnum.ARCHIVED.getIntValue(), "票据已归档,不允许审核");
        Assert.isFalse(bean.getStatus() == ApprovEnum.VOIDED.getIntValue(), "票据已作废,不允许审核");

        // 已生成状态下 撤回
        if (bean.getStatus() == ApprovEnum.REVIEWED.getIntValue()) {
            //厂站操作票 已生成 也允许撤回 20220310
            if (bean.getGroup().equals(OperationGroupEnum.FactoryTicket.getValue()) && dto.getSubmitType() == SubmitEnum.FAIL.getIntValue()) {
                // 清除执行信息
                ADOConnection.runTask(getCurrDs(), factory -> {
                    factory.getMapper(OperationExecuteMapper.class).deleteByOperationId(dto.getId());
                    return true;
                }, Boolean.class);
            } else {
                Assert.isFalse(dto.getSubmitType() == SubmitEnum.FAIL.getIntValue(), "票据已复审,不允许撤回");
            }

        }

        if (bean.getStatus() == ApprovEnum.REVIEWED.getIntValue() && dto.getSubmitType() == SubmitEnum.ADOPT.getIntValue()) {
            // 执行信息
            OperationExecuteBean executebean = ADOConnection.runTask(getCurrDs(), factory -> {
                return factory.getMapper(OperationExecuteMapper.class).queryByOperationId(dto.getId());
            }, OperationExecuteBean.class);

            if (dto.getSubmitType() == SubmitEnum.ADOPT.getIntValue()) {
                Assert.isFalse(executebean.getEndTime() == null, "归档需要补充 执行终了时间");
            }

            // 操作步骤
            List<OperationStepBean> steplist = ADOConnection.runTask(getCurrDs(), factory -> {
                return factory.getMapper(OperationStepMapper.class).queryAllByOperationId(dto.getId());
            }, List.class);

            if (StringUtils.isNotEmpty(steplist)) {
                steplist.stream().filter(s -> StringUtils.isNotEmpty(s.getParentId())).forEach(s -> {
                    if (StringUtils.isEmpty(s.getAcceptMan()) || StringUtils.isEmpty(s.getReportMan())) {
                        Assert.isFalse(true, "请填写受令人报告人");
                        return;
                    }
                });
            }
        }

        return Response.ok(ADOConnection.runTask(getCurrDs(), operationservice, "submit", Integer.class, dto));
    }


    @ApiOperation(value = "下载excel操作步骤明细  type=1 厂站  type=2调度")
    @GetMapping("/downExcelDetStepdetTemplate")
    public void downExcelDetStepdetTemplate(HttpServletResponse rsp, Integer type) {

        EamUser eamUser = ThreadLocalContext.get();

        List<OperationFactoryTemplate> childrentemplate = new ArrayList<>();        //厂站
        List<OperationStepTemplate> templateslist = new ArrayList<>();              //调度
        try {
            if (type == OperationGroupEnum.FactoryTicket.getKey()) {
                childrentemplate = InitData.getChangZhanTemplates(eamUser, 4);
                ExportExcelUtil.exportExcel(childrentemplate, OperationFactoryTemplate.class, "厂站操作步骤模板", rsp);
            }
            if (type == OperationGroupEnum.DispatchTicket.getKey()) {
                InitData.InitStepData(eamUser, templateslist);//初始话操作步骤模板数据
                ExportExcelUtil.exportExcel(templateslist, OperationStepTemplate.class, "调度操作步骤模板", rsp);
            }
        } catch (Exception e) {
            log.error("操作步骤模板导出失败");
            log.error(e.getMessage(), e);
        }
        return;
    }

    @ApiOperation(value = "导出厂站界面操作步骤明细 厂站")
    @PostMapping("/downFactoryExcelDetStepdet")
    public void downFactoryExcelDetStepdet(HttpServletResponse rsp, @RequestBody List<OperationFactoryTemplate> listdto) {
        try {
            ExportExcelUtil.exportExcel(listdto, OperationFactoryTemplate.class, "厂站操作步骤模板", rsp);
        } catch (Exception e) {
            String errStr = "操作步骤导出失败";
            log.error(errStr);
            Assert.isFalse(true, errStr);
            log.error(e.getMessage(), e);
        }
    }

    @ApiOperation(value = "导出调度界面操作步骤明细 调度")
    @PostMapping("/downDispatchExcelDetStepdet")
    public void downExcelDetStepdet(HttpServletResponse rsp, @RequestBody List<OperationStepTemplate> listdto) {
        try {
            ExportExcelUtil.exportExcel(listdto, OperationStepTemplate.class, "调度操作步骤模板", rsp);
        } catch (Exception e) {
            String errStr = "操作步骤导出失败";
            log.error(errStr);
            Assert.isFalse(true, errStr);
            log.error(e.getMessage(), e);
        }
    }

    @ApiOperation(value = "检查是否关联操作票")
    @PostMapping("/checkRelation")
    public Response checkRelation(@RequestParam("workTicketId") String workTicketId) {

        CheckRelationDto res = ADOConnection.runTask(getCurrDs(), factory -> {
            CheckRelationDto temp = new CheckRelationDto();
            OperationWorkMapper mapper = factory.getMapper(OperationWorkMapper.class);
            List<OperationTicketBean> list = mapper.queryByWorkIdAndStatus(workTicketId, SubmitEnum.TOCANCEL.getIntValue());
            if (CollUtil.isNotEmpty(list)) {
                Optional<OperationTicketBean> ap = list.stream().filter(t -> t.getType().equals(OperationTypeEnum.TYPE_A.getValue())).findFirst();
                Optional<OperationTicketBean> bp = list.stream().filter(t -> t.getType().equals(OperationTypeEnum.TYPE_B.getValue())).findFirst();
                temp.setOperationAticket(ap.map(OperationTicketBean::getId).orElse(null));
                temp.setOperationBticket(bp.map(OperationTicketBean::getId).orElse(null));
            }
            return temp;
        }, CheckRelationDto.class);
        return Response.ok(res);
    }

    @ApiOperation(value = "检查是否关联操作票pro")
    @PostMapping("/checkRelationPro")
    public Response checkRelationPro(@RequestParam("workTicketId") String workTicketId) {

        List<OperationTicketBean> res = ADOConnection.runTask(getCurrDs(), factory -> {
            OperationWorkMapper mapper = factory.getMapper(OperationWorkMapper.class);
            List<OperationTicketBean> list = mapper.queryByWorkId(workTicketId);
            return list;
        }, List.class);
        return Response.ok(res);
    }


    @ApiOperation(value = "导入excel,返回步骤明细 type=1 厂站  type=2调度")
    @PostMapping("/excelImpDetStepdet")
    public Response excelImpDetStepdet(@RequestParam("file") MultipartFile multipartFile, Integer type) throws Exception {

        if (type == OperationGroupEnum.FactoryTicket.getKey()) {
            ExcelImportResult<OperationFactoryTemplate> result;
            ImportParams params = new ImportParams();
            // 表头设置为2行
            params.setHeadRows(1);
            // 标题行设置为0行，默认是0，可以不设置
            params.setTitleRows(0);
            result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), OperationFactoryTemplate.class, params);
            List<OperationFactoryTemplate> list = result.getList();
            return Response.ok(list);
        }
        if (type == OperationGroupEnum.DispatchTicket.getKey()) {
            ExcelImportResult<OperationStepTemplate> result;
            ImportParams params = new ImportParams();
            // 表头设置为2行
            params.setHeadRows(2);
            // 标题行设置为0行，默认是0，可以不设置
            params.setTitleRows(0);
            result = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), OperationStepTemplate.class, params);
            List<OperationStepTemplate> list = result.getList();
            OperationStepBaseTemplate checkresult = ADOConnection.runTask("_default", operationservice, "checkForDuplicates", OperationStepBaseTemplate.class, result.getList());
            Assert.isFalse(StringUtils.isNotEmpty(checkresult.getErrorMsg()), checkresult.getErrorMsg());

            return Response.ok(list);
        }
        return null;
    }

    /**
     * 打印操作票
     *
     * @param user
     * @return
     */
    @ApiOperation(value = "打印操作票 (需要先 安装 打印控件) type=1 厂站  type=2调度")
    @SuppressWarnings("unchecked")
    @GetMapping("/printOperation.htm")
    public Response printOutStockdet(@ApiIgnore @CasUser EamUser user, String id, Integer type) {

        List<OperationFactoryBean> list = ADOConnection.runTask(getCurrDs(), operationservice, "printOperation", ArrayList.class, id);

        String printTemplateId = "";
        if (type == Integer.valueOf(1)) {
            printTemplateId = PrintUtils.getDefaultPrintTemplateId("factory");
        }
        if (type == Integer.valueOf(2)) {
            printTemplateId = PrintUtils.getDefaultPrintTemplateId("dispatch");
        }

        String url = ReportTask.printData(user, printTemplateId, list);//存储打印数据，以及返回打印地址

        return Response.ok("获取成功，拿返回地址回调打印", url);
    }


}
